/**
 * 
 */
package com.ecp.util;

import java.io.StringReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

/**
 * @author jyou
 *
 */
public class XmlFileUtil {

	public void xmlToObject(Object obj, Element element, String packagePath) throws Exception {

		List<Element> elements = element.elements();
		for (Element el : elements) {
			List<Element> subEl = el.elements(); // flights
			setNodeValue(obj, el);
			boolean one = setAttribute(obj, el);

			if (subEl.size() > 0) {
				List list2 = new ArrayList();
				for (Element el2 : subEl) {
					String classPath = packagePath + "." + firstToUpperCase(el2.getName());
					Object obj2 = Class.forName(classPath).newInstance();
					List<Element> subEl2 = el2.elements(); // flight
					setAttribute(obj2, el2);
					setNodeValue(obj2, el2);
					if (subEl2.size() > 0) {
						for (Element el3 : subEl2) {
							List<Element> subEl3 = el3.elements(); // cabins
							if (subEl3.size() > 0) {
								List list3 = new ArrayList();
								for (Element el4 : subEl3) {
									String classPath2 = packagePath + "."
											+ firstToUpperCase(el4.getName());
									Object obj4 = Class.forName(classPath2).newInstance();
									setAttribute(obj4, el4);
									setNodeValue(obj4, el);
									list3.add(obj4);
								}
								this.invokeMethod(this.setMethodName(el3.getName()), obj2, list3);
							}
						}
					}
					list2.add(obj2);
				}
				this.invokeMethod(this.setMethodName(el.getName()), obj, list2);
			} else {
				if (one) {
					String classPath = packagePath + "." + el.getName();
					Object objOne = Class.forName(classPath).newInstance();
					setAttribute(objOne, el);
					this.invokeMethod(this.setMethodName(el.getName()), obj, objOne);
				}
			}
		}
	}

	/**
	 * @function:设置节点值
	 * @param obj 要初始化的bean
	 * @param element 文档元素
	 * @throws Exception
	 */
	private void setNodeValue(Object obj, Element element) throws Exception {

		String attributeName = element.getName();
		String value = null;
		value = element.getText();
		if (StringUtils.isNotBlank(value)) {
			this.invokeMethod(this.setMethodName(attributeName), obj, value);
		}

	}

	/**
	 * @function:设置节点的属性
	 * @param obj
	 *            要初始化的bean
	 * @param element
	 *            文档元素
	 * @throws Exception
	 */
	private boolean setAttribute(Object obj, Element element) throws Exception {
		boolean ishasAttr = false;
		for (Iterator it = element.attributeIterator(); it.hasNext();) {// 遍历当前节点的所有属性
			ishasAttr = true;
			Attribute attribute = (Attribute) it.next();
			Field[] field = obj.getClass().getDeclaredFields();
			for (int i = 0; i < field.length; i++) { // 根据xml内容赋值到对象中，使用对象中默认值不需要重新赋值
				if (field[i].getName().equals(attribute.getName())) {
					// System.out.print(" "+field[i].getName());
					this.invokeMethod(this.setMethodName(field[i].getName()), obj,
							attribute.getText());
				}
			}
		}
		return ishasAttr;
		// System.out.println("");
	}

	/**
	 * @function:执行方法
	 * @param methodName
	 *            方法名
	 * @param object
	 *            方法所在对象
	 * @param value
	 *            方法中的参数值
	 */
	private void invokeMethod(String methodName, Object object, String value)
			throws IllegalArgumentException, IllegalAccessException, InvocationTargetException,
			SecurityException, NoSuchMethodException {
		
		Method method = object.getClass().getMethod(methodName, String.class);
		method.invoke(object, value);
	}

	/**
	 * @function:执行方法
	 * @param methodName
	 *            方法名
	 * @param object
	 *            方法所在对象
	 * @param value
	 *            方法中的参数值
	 */
	private void invokeMethod(String methodName, Object object, Object value)
			throws IllegalArgumentException, IllegalAccessException, InvocationTargetException,
			SecurityException, NoSuchMethodException {
		
		Method method = object.getClass().getMethod(methodName, value.getClass());
		method.invoke(object, value);
	}

	/**
	 * @function:执行方法
	 * @param methodName
	 *            方法名
	 * @param object
	 *            方法所在对象
	 * @param value
	 *            方法中的参数值
	 */
	private void invokeMethod(String methodName, Object object, List<T> value)
			throws IllegalArgumentException, IllegalAccessException, InvocationTargetException,
			SecurityException, NoSuchMethodException {
		
		Method method = object.getClass().getMethod(methodName, List.class);
		method.invoke(object, value);
	}

//	/**
//	 * 
//	 * @function:执行方法
//	 * @param methodName
//	 *            方法名
//	 * @param object
//	 *            方法所在对象
//	 * @return
//	 */
//	private Object invokeMethod(String methodName, Object object) throws IllegalArgumentException,
//			IllegalAccessException, InvocationTargetException, SecurityException,
//			NoSuchMethodException {
//		
//		Method method = object.getClass().getMethod(methodName);
//		return method.invoke(object);
//	}

//	/**
//	 * 
//	 * @function:获得属性值
//	 * @param field
//	 *            属性对象
//	 * @param object
//	 *            属性所属类对象
//	 * @return
//	 */
//	private Object getField(Field field, Object object) throws IllegalArgumentException,
//			IllegalAccessException {
//		field.setAccessible(true);// 设置属性可以修改
//		return field.get(object);
//	}

//	/**
//	 * 
//	 * @function:通过属性生成get方法名
//	 * @param str
//	 * @return
//	 */
//	private String getMethodName(String str) {
//		return "get" + firstToUpperCase(str);
//	}

	/**
	 * 
	 * @function:通过属性生成set方法名
	 * @param str
	 * @return
	 */
	private String setMethodName(String str) {
		return "set" + firstToUpperCase(str);
	}

	/**
	 * 首字母大写
	 */
	private String firstToUpperCase(String str) {
		char[] cs = str.toCharArray();
		cs[0] -= 32;
		return String.valueOf(cs);
	}

	public static Element getRootElement(String str) throws Exception {

		StringReader read = new StringReader(str);
		InputSource source = new InputSource(read);
		SAXReader sax = new SAXReader();

		Document doc = sax.read(source);
		Element root = doc.getRootElement();
		return root;
	}

}
